
`include "IF_AHB_paras.vh"

module ahb_arbiter(
    input           clk,
    input           rst_n,
    
    input           i_hbusreq,
    output          i_hgrant,    

    input [1:0]     i_hresp,
    input           i_hready,
    
    input           d_hbusreq,
    output          d_hgrant,

    input [1:0]     d_hresp,
    input           d_hready    
);

reg [1:0] hgrant_current;
reg [1:0] hgrant_current_nx;
reg [1:0] hgrant_pre;
reg [1:0] hgrant_pre_nx;

assign i_hgrant = hgrant_current[0];
assign d_hgrant = hgrant_current[1];

always@(*) begin
    hgrant_current_nx = hgrant_current;
    hgrant_pre_nx = hgrant_pre;
    
    if(|hgrant_current) begin
        if(hgrant_current[0] & (i_hresp == `RESP_OKAY) & i_hready) begin
            hgrant_current_nx[0] = 1'b0;
            hgrant_pre_nx[0] = 1'b1;
            hgrant_pre_nx[1] = 1'b0;
        end
        if(hgrant_current[1] & (d_hresp == `RESP_OKAY) & d_hready) begin
            hgrant_current_nx[1] = 1'b0;
            hgrant_pre_nx[0] = 1'b0;
            hgrant_pre_nx[1] = 1'b1;
            
        end
    end
    else begin
        case(hgrant_pre[1:0])
            2'b00: begin
                case(1'b1)
                    i_hbusreq:hgrant_current_nx[0] = 1'b1;
                    d_hbusreq:hgrant_current_nx[1] = 1'b1;
                endcase
            end
            2'b01: begin
                case(1'b1)
                    d_hbusreq:hgrant_current_nx[1] = 1'b1;
                    i_hbusreq:hgrant_current_nx[0] = 1'b1;
                endcase               
            end
            2'b10: begin
                case(1'b1)
                    i_hbusreq:hgrant_current_nx[0] = 1'b1;
                    d_hbusreq:hgrant_current_nx[1] = 1'b1;
                endcase           
            end
            default: begin
                hgrant_current_nx = 'd0;
            end
        endcase
    end
end

always@(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        hgrant_current <= 2'b00;
        hgrant_pre <= 2'b00;
    end
    else begin
        hgrant_current <= hgrant_current_nx;
        hgrant_pre <= hgrant_pre_nx;
    end
end

endmodule
